package cn.org.donald.sensitive.factory;

import cn.org.donald.sensitive.model.FactoryEnum;
import cn.org.donald.sensitive.util.StringUtil;
import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.sl.extractor.SlideShowExtractor;
import org.apache.poi.xslf.usermodel.*;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Donald
 * @since 2023-11-10 17:05:57
 **/
public class PowerPointFindSensitive extends IFindSensitive {

    public PowerPointFindSensitive(Path filePath, FactoryEnum factoryEnum) {
        super(filePath, factoryEnum);
    }

    @Override
    public List<String> getSensitiveString(List<String> ruleRegexList) {
        String text;
        try (InputStream inputStream = Files.newInputStream(super.getFilePath())) {
            if (FactoryEnum.PPT.equals(super.getFactoryEnum())) {
                text = getPptString(inputStream);
            } else {
                text = getPptxString(inputStream);
            }
            return super.findSensitiveInString(ruleRegexList, text).collect(Collectors.toList());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void replace(List<String> ruleRegexList, Path destPath) {
        String regex = String.join("|", ruleRegexList);
        try {
            Files.deleteIfExists(destPath);
            Files.createDirectories(destPath.getParent());
            Files.createFile(destPath);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        try (InputStream inputStream = Files.newInputStream(super.getFilePath())) {
            if (FactoryEnum.PPTX.equals(super.getFactoryEnum())) {
                replacePptx(inputStream, destPath, regex);
            } else {
                replacePpt(inputStream, destPath, regex);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private String getPptString(InputStream inputStream) {
        try (HSLFSlideShow hslfSlideShow = new HSLFSlideShow(inputStream)) {
            SlideShowExtractor<HSLFShape, HSLFTextParagraph> showExtractor = new SlideShowExtractor<>(hslfSlideShow);
            return showExtractor.getText();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private String getPptxString(InputStream inputStream) {
        try (XMLSlideShow xmlSlideShow = new XMLSlideShow(inputStream)) {
            SlideShowExtractor<XSLFShape, XSLFTextParagraph> showExtractor = new SlideShowExtractor<>(xmlSlideShow);
            return showExtractor.getText();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private void replacePptx(InputStream inputStream, Path destPath, String regex) {
        try (XMLSlideShow xmlSlideShow = new XMLSlideShow(inputStream)) {
            List<XSLFSlide> slides = xmlSlideShow.getSlides();
            for (XSLFSlide slide : slides) {
                List<XSLFShape> shapes = slide.getShapes();
                for (XSLFShape shape : shapes) {
                    if (shape instanceof XSLFTextShape) {
                        XSLFTextShape textShape = (XSLFTextShape) shape;
                        List<XSLFTextParagraph> textParagraphs = textShape.getTextParagraphs();
                        for (XSLFTextParagraph textParagraph : textParagraphs) {
                            List<XSLFTextRun> textRuns = textParagraph.getTextRuns();
                            for (XSLFTextRun textRun : textRuns) {
                                String rawText = textRun.getRawText();
                                // TODO 替换
                                String replacement = StringUtil.replaceTargetToStar(rawText, regex);
                                // TODO 写入
                                textRun.setText(replacement);
                            }
                        }
                    }
                }
            }
            try (OutputStream outputStream = Files.newOutputStream(destPath, StandardOpenOption.WRITE)) {
                xmlSlideShow.write(outputStream);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private void replacePpt(InputStream inputStream, Path destPath, String regex) {
        try (HSLFSlideShow hslfSlideShow = new HSLFSlideShow(inputStream)) {
            List<HSLFSlide> slides = hslfSlideShow.getSlides();
            for (HSLFSlide slide : slides) {
                List<HSLFShape> shapes = slide.getShapes();
                for (HSLFShape shape : shapes) {
                    if (shape instanceof HSLFTextShape) {
                        HSLFTextShape textShape = (HSLFTextShape) shape;
                        List<HSLFTextParagraph> textParagraphs = textShape.getTextParagraphs();
                        for (HSLFTextParagraph textParagraph : textParagraphs) {
                            List<HSLFTextRun> textRuns = textParagraph.getTextRuns();
                            for (HSLFTextRun textRun : textRuns) {
                                String rawText = textRun.getRawText();
                                // 替换
                                String replacement = StringUtil.replaceTargetToStar(rawText, regex);
                                // 写入
                                textRun.setText(replacement);
                            }
                        }
                    }
                }
            }
            try (OutputStream outputStream = Files.newOutputStream(destPath, StandardOpenOption.WRITE)) {
                hslfSlideShow.write(outputStream);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
